/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bff.spi;

import com.inspur.edp.bff.api.dataprocessor.IDataConvertor;
import com.inspur.edp.bff.api.exception.BffFrameworkException;
import com.inspur.edp.bff.api.exception.ErrorCodes;
import com.inspur.edp.bff.api.manager.IFSManager;
import com.inspur.edp.cef.entity.accessor.base.IAccessor;
import com.inspur.edp.cef.entity.entity.EntityDataCollection;
import com.inspur.edp.cef.entity.entity.ICefData;
import com.inspur.edp.cef.entity.entity.IEntityData;
import com.inspur.edp.cef.entity.entity.IEntityDataCollection;
import com.inspur.edp.cef.entity.entity.IMultiLanguageData;

import java.util.HashMap;
import java.util.Map;

public abstract class AbstractDataConvertor implements IDataConvertor {

    private IFSManager fsManager;

    /**
     * 构造函数
     */

    public AbstractDataConvertor() {

    }

    public final IFSManager getFSManager() {
        return fsManager;
    }

    public final void setFSManager(IFSManager value) {
        fsManager = value;
    }

    /**
     * 将BE数据转换成VM数据
     *
     * @param beData BE数据
     * @param vmData VM数据
     * @see IEntityData
     */
    public final void convertFromBEData(IEntityData beData, IEntityData vmData) {
        mappingEntityDataProperties(beData, vmData);

        if (beData instanceof IMultiLanguageData && vmData instanceof IMultiLanguageData) {
            mappingEntityDataMultiLanguageProps(beData, vmData);
        }

        HashMap<String, IEntityDataCollection> childs = beData.getChilds();
        if (childs == null || childs.size() == 0) {
            return;
        }

        for (Map.Entry<String, IEntityDataCollection> item : childs.entrySet()) {
            convertChild(item.getKey(), item.getValue(), vmData);
        }
    }

    private void convertChild(String childCode, IEntityDataCollection datas, IEntityData vmData) {
        if (datas == null || datas.size() == 0 || !checkChildCode(childCode)) {
            return;
        }
        AbstractDataConvertor childConvertor = getChildDataConvertor(childCode);

        if (childConvertor == null) {
            return;
        }

        for (IEntityData item : datas) {
            Object tempVar = (getFSManager() == null ? vmData.createChild(childCode) : ((IAccessor) getFSManager().createChildData(childCode, "")).getInnerData());
            IEntityData vmChild = (IEntityData) (getFSManager() == null ? vmData.createChild(childCode) : ((IAccessor) getFSManager().createChildData(childCode, "")).getInnerData());
            if (vmChild == null)
            //TODO 异常封装
            {
                throw new BffFrameworkException();
            }
            childConvertor.convertFromBEData(item, vmChild);

            HashMap<String, IEntityDataCollection> childDatas = vmData.getChilds();
            if (childDatas.containsKey(childCode)) {
                childDatas.get(childCode).add(vmChild);
            } else {
                EntityDataCollection collection = new EntityDataCollection();
                collection.add(vmChild);
                childDatas.put(childCode, collection);
            }
        }
    }

    protected boolean checkChildCode(String childCode) {
        return true;
    }


    /**
     * 将BE数据属性映射到VM数据实体上
     *
     * @param beData BE数据
     * @param vmData VM数据
     * @see IEntityData
     */
    protected abstract void mappingEntityDataProperties(IEntityData beData, IEntityData vmData);

    protected void mappingEntityDataMultiLanguageProps(IEntityData beData, IEntityData vmData) {

    }

    protected void mappingEntityDataPropertiesFromVo(IEntityData beData, IEntityData vmData) {
        throw new BffFrameworkException(ErrorCodes.BFF_FRAMEWORK_2009);
    }

    protected void mappingEntityDataMultiLanguagePropsFromVo(IEntityData beData,
                                                             IEntityData vmData) {

    }

    /**
     * 获取子节点的数据转换器
     *
     * @param childCode 子节点编号
     * @return 得到的子节点的数据转换器
     * @see AbstractDataConvertor
     */
    public abstract AbstractDataConvertor getChildDataConvertor(String childCode);

    public final IDataConvertor getChildConvertor(String childCode) {
        if (checkChildCode(childCode))
            return getChildDataConvertor(childCode);
        return null;
    }
    //TODO：暂时未实现。

    /**
     * 将VM数据转换成BE数据
     *
     * @param vmData VM数据
     * @param beData BE数据
     * @see IEntityData
     */
    public final void convertFromVMData(IEntityData vmData, IEntityData beData) {
        mappingEntityDataPropertiesFromVo(beData, vmData);
        if (beData instanceof IMultiLanguageData && vmData instanceof IMultiLanguageData) {
            mappingEntityDataMultiLanguagePropsFromVo(beData, vmData);
        }
        HashMap<String, IEntityDataCollection> childs = vmData.getChilds();
        if (childs == null || childs.size() == 0) {
            return;
        }

        for (Map.Entry<String, IEntityDataCollection> item : childs.entrySet()) {
            convertChildFromVo(item.getKey(), item.getValue(), beData);
        }
    }

    private void convertChildFromVo(String childCode, IEntityDataCollection datas, IEntityData beData) {
        if (datas == null || datas.size() == 0 || !checkChildCode(childCode)) {
            return;
        }
        AbstractDataConvertor childConvertor = getChildDataConvertor(childCode);

        if (childConvertor == null) {
            return;
        }

        for (IEntityData item : datas) {
            ICefData tempVar = beData.createChild(childCode);
            IEntityData beChild = (IEntityData) ((tempVar instanceof IEntityData) ? tempVar : null);
            if (beChild == null)
            //TODO 异常封装
            {
                throw new BffFrameworkException();
            }
            childConvertor.convertFromVMData(item, beChild);

            HashMap<String, IEntityDataCollection> childDatas = beData.getChilds();
            if (childDatas.containsKey(childCode)) {
                childDatas.get(childCode).add(beChild);
            } else {
                EntityDataCollection collection = new EntityDataCollection();
                collection.add(beChild);
                childDatas.put(childCode, collection);

            }
        }
    }

    public final void convertFromSourceData(ICefData sourceData, IEntityData vmData) {
        throw new UnsupportedOperationException();
    }

    public final void convert2SourceData(IEntityData vmData, ICefData sourceData) {
        throw new UnsupportedOperationException();
    }
}
